package org.fisco.bcos.sdk.demo.contract;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.fisco.bcos.sdk.v3.client.Client;
import org.fisco.bcos.sdk.v3.codec.datatypes.Address;
import org.fisco.bcos.sdk.v3.codec.datatypes.Bool;
import org.fisco.bcos.sdk.v3.codec.datatypes.DynamicBytes;
import org.fisco.bcos.sdk.v3.codec.datatypes.Event;
import org.fisco.bcos.sdk.v3.codec.datatypes.Function;
import org.fisco.bcos.sdk.v3.codec.datatypes.Type;
import org.fisco.bcos.sdk.v3.codec.datatypes.TypeReference;
import org.fisco.bcos.sdk.v3.codec.datatypes.Utf8String;
import org.fisco.bcos.sdk.v3.codec.datatypes.generated.Bytes32;
import org.fisco.bcos.sdk.v3.codec.datatypes.generated.tuples.generated.Tuple2;
import org.fisco.bcos.sdk.v3.codec.datatypes.generated.tuples.generated.Tuple8;
import org.fisco.bcos.sdk.v3.contract.Contract;
import org.fisco.bcos.sdk.v3.crypto.CryptoSuite;
import org.fisco.bcos.sdk.v3.crypto.keypair.CryptoKeyPair;
import org.fisco.bcos.sdk.v3.model.CryptoType;
import org.fisco.bcos.sdk.v3.model.TransactionReceipt;
import org.fisco.bcos.sdk.v3.model.callback.TransactionCallback;
import org.fisco.bcos.sdk.v3.transaction.model.exception.ContractException;

@SuppressWarnings("unchecked")
public class SM2EvidenceVerify extends Contract {
    public static final String[] BINARY_ARRAY = {
        "608060405234801561001057600080fd5b50600080546001600160a01b03191661100a179055610bb5806100346000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063d7f8df1514610030575b600080fd5b61004361003e366004610288565b610066565b6040805192151583526001600160a01b0390911660208301520160405180910390f35b60008060008a8a8a60405161007a906101b0565b610086939291906103b0565b604051809103906000f0801580156100a2573d6000803e3d6000fd5b506040516001600160a01b03821681529091507f8b94c7f6b3fadc764673ea85b4bfef3e17ce928d13e51b818ddfa891ad0f1fcc9060200160405180910390a16000806100f18989898961012c565b925090506001600160a01b03808316908b161461010d57600080fd5b60018115151461011c57600080fd5b5050509850989650505050505050565b6000805460405163cbdb3a6760e01b815282916001600160a01b03169063cbdb3a67906101639089908990899089906004016103f3565b6040805180830381865afa15801561017f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101a3919061041f565b9150915094509492505050565b6107218061045f83390190565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126101e457600080fd5b813567ffffffffffffffff808211156101ff576101ff6101bd565b604051601f8301601f19908116603f01168101908282118183101715610227576102276101bd565b8160405283815286602085880101111561024057600080fd5b836020870160208301376000602085830101528094505050505092915050565b6001600160a01b038116811461027557600080fd5b50565b803561028381610260565b919050565b600080600080600080600080610100898b0312156102a557600080fd5b883567ffffffffffffffff808211156102bd57600080fd5b6102c98c838d016101d3565b995060208b01359150808211156102df57600080fd5b6102eb8c838d016101d3565b985060408b013591508082111561030157600080fd5b61030d8c838d016101d3565b975061031b60608c01610278565b965060808b0135955060a08b013591508082111561033857600080fd5b506103458b828c016101d3565b93505060c0890135915060e089013590509295985092959890939650565b6000815180845260005b818110156103895760208185018101518683018201520161036d565b8181111561039b576000602083870101525b50601f01601f19169290920160200192915050565b6060815260006103c36060830186610363565b82810360208401526103d58186610363565b905082810360408401526103e98185610363565b9695505050505050565b84815260806020820152600061040c6080830186610363565b6040830194909452506060015292915050565b6000806040838503121561043257600080fd5b8251801515811461044257600080fd5b602084015190925061045381610260565b80915050925092905056fe608060405234801561001057600080fd5b5060405161072138038061072183398101604081905261002f91610214565b82516100429060009060208601906100ae565b5081516100569060019060208501906100ae565b50805161006a9060029060208401906100ae565b507faf1f4f8d84431b65de566a0a4f73763572c14edb25a1360312ff3c7b5386191183838360405161009e939291906102c7565b60405180910390a150505061033b565b8280546100ba90610300565b90600052602060002090601f0160209004810192826100dc5760008555610122565b82601f106100f557805160ff1916838001178555610122565b82800160010185558215610122579182015b82811115610122578251825591602001919060010190610107565b5061012e929150610132565b5090565b5b8082111561012e5760008155600101610133565b634e487b7160e01b600052604160045260246000fd5b60005b83811015610178578181015183820152602001610160565b83811115610187576000848401525b50505050565b600082601f83011261019e57600080fd5b81516001600160401b03808211156101b8576101b8610147565b604051601f8301601f19908116603f011681019082821181831017156101e0576101e0610147565b816040528381528660208588010111156101f957600080fd5b61020a84602083016020890161015d565b9695505050505050565b60008060006060848603121561022957600080fd5b83516001600160401b038082111561024057600080fd5b61024c8783880161018d565b9450602086015191508082111561026257600080fd5b61026e8783880161018d565b9350604086015191508082111561028457600080fd5b506102918682870161018d565b9150509250925092565b600081518084526102b381602086016020860161015d565b601f01601f19169290920160200192915050565b6060815260006102da606083018661029b565b82810360208401526102ec818661029b565b9050828103604084015261020a818561029b565b600181811c9082168061031457607f821691505b6020821081141561033557634e487b7160e01b600052602260045260246000fd5b50919050565b6103d78061034a6000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063596f21f81461003b578063c7eaf9b41461005b575b600080fd5b610043610070565b60405161005293929190610309565b60405180910390f35b61006361022a565b604051610052919061034c565b606080606060006001600282805461008790610366565b80601f01602080910402602001604051908101604052809291908181526020018280546100b390610366565b80156101005780601f106100d557610100808354040283529160200191610100565b820191906000526020600020905b8154815290600101906020018083116100e357829003601f168201915b5050505050925081805461011390610366565b80601f016020809104026020016040519081016040528092919081815260200182805461013f90610366565b801561018c5780601f106101615761010080835404028352916020019161018c565b820191906000526020600020905b81548152906001019060200180831161016f57829003601f168201915b5050505050915080805461019f90610366565b80601f01602080910402602001604051908101604052809291908181526020018280546101cb90610366565b80156102185780601f106101ed57610100808354040283529160200191610218565b820191906000526020600020905b8154815290600101906020018083116101fb57829003601f168201915b50505050509050925092509250909192565b60606001805461023990610366565b80601f016020809104026020016040519081016040528092919081815260200182805461026590610366565b80156102b25780601f10610287576101008083540402835291602001916102b2565b820191906000526020600020905b81548152906001019060200180831161029557829003601f168201915b5050505050905090565b6000815180845260005b818110156102e2576020818501810151868301820152016102c6565b818111156102f4576000602083870101525b50601f01601f19169290920160200192915050565b60608152600061031c60608301866102bc565b828103602084015261032e81866102bc565b9050828103604084015261034281856102bc565b9695505050505050565b60208152600061035f60208301846102bc565b9392505050565b600181811c9082168061037a57607f821691505b6020821081141561039b57634e487b7160e01b600052602260045260246000fd5b5091905056fea26469706673582212201f422aa8bca25276ec3c207464838621add881a0a9203f27e890ff80c72121bb64736f6c634300080b0033a26469706673582212203c1f4c66c310a3b0d9e37eb5b2f4fd269393ec507063d487b021f53ea17ed7d564736f6c634300080b0033"
    };

    public static final String BINARY =
            org.fisco.bcos.sdk.v3.utils.StringUtils.joinAll("", BINARY_ARRAY);

    public static final String[] SM_BINARY_ARRAY = {
        "608060405234801561001057600080fd5b50600080546001600160a01b03191661100a179055610bb5806100346000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c80639dbd28b114610030575b600080fd5b61004361003e366004610288565b610066565b6040805192151583526001600160a01b0390911660208301520160405180910390f35b60008060008a8a8a60405161007a906101b0565b610086939291906103b0565b604051809103906000f0801580156100a2573d6000803e3d6000fd5b506040516001600160a01b03821681529091507ffce723060091dd1452a91ae12d05541e3141b37fa27968bc557add04601f74d09060200160405180910390a16000806100f18989898961012c565b925090506001600160a01b03808316908b161461010d57600080fd5b60018115151461011c57600080fd5b5050509850989650505050505050565b60008054604051631176f30f60e11b815282916001600160a01b0316906322ede61e906101639089908990899089906004016103f3565b6040805180830381865afa15801561017f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101a3919061041f565b9150915094509492505050565b6107218061045f83390190565b63b95aa35560e01b600052604160045260246000fd5b600082601f8301126101e457600080fd5b813567ffffffffffffffff808211156101ff576101ff6101bd565b604051601f8301601f19908116603f01168101908282118183101715610227576102276101bd565b8160405283815286602085880101111561024057600080fd5b836020870160208301376000602085830101528094505050505092915050565b6001600160a01b038116811461027557600080fd5b50565b803561028381610260565b919050565b600080600080600080600080610100898b0312156102a557600080fd5b883567ffffffffffffffff808211156102bd57600080fd5b6102c98c838d016101d3565b995060208b01359150808211156102df57600080fd5b6102eb8c838d016101d3565b985060408b013591508082111561030157600080fd5b61030d8c838d016101d3565b975061031b60608c01610278565b965060808b0135955060a08b013591508082111561033857600080fd5b506103458b828c016101d3565b93505060c0890135915060e089013590509295985092959890939650565b6000815180845260005b818110156103895760208185018101518683018201520161036d565b8181111561039b576000602083870101525b50601f01601f19169290920160200192915050565b6060815260006103c36060830186610363565b82810360208401526103d58186610363565b905082810360408401526103e98185610363565b9695505050505050565b84815260806020820152600061040c6080830186610363565b6040830194909452506060015292915050565b6000806040838503121561043257600080fd5b8251801515811461044257600080fd5b602084015190925061045381610260565b80915050925092905056fe608060405234801561001057600080fd5b5060405161072138038061072183398101604081905261002f91610214565b82516100429060009060208601906100ae565b5081516100569060019060208501906100ae565b50805161006a9060029060208401906100ae565b507f862dc616a336d85acf6c0a863ee6e67b03a19d22753b3455d915fddcdc414ea483838360405161009e939291906102c7565b60405180910390a150505061033b565b8280546100ba90610300565b90600052602060002090601f0160209004810192826100dc5760008555610122565b82601f106100f557805160ff1916838001178555610122565b82800160010185558215610122579182015b82811115610122578251825591602001919060010190610107565b5061012e929150610132565b5090565b5b8082111561012e5760008155600101610133565b63b95aa35560e01b600052604160045260246000fd5b60005b83811015610178578181015183820152602001610160565b83811115610187576000848401525b50505050565b600082601f83011261019e57600080fd5b81516001600160401b03808211156101b8576101b8610147565b604051601f8301601f19908116603f011681019082821181831017156101e0576101e0610147565b816040528381528660208588010111156101f957600080fd5b61020a84602083016020890161015d565b9695505050505050565b60008060006060848603121561022957600080fd5b83516001600160401b038082111561024057600080fd5b61024c8783880161018d565b9450602086015191508082111561026257600080fd5b61026e8783880161018d565b9350604086015191508082111561028457600080fd5b506102918682870161018d565b9150509250925092565b600081518084526102b381602086016020860161015d565b601f01601f19169290920160200192915050565b6060815260006102da606083018661029b565b82810360208401526102ec818661029b565b9050828103604084015261020a818561029b565b600181811c9082168061031457607f821691505b602082108114156103355763b95aa35560e01b600052602260045260246000fd5b50919050565b6103d78061034a6000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80634ae70cef1461003b578063995297f31461005b575b600080fd5b610043610070565b60405161005293929190610309565b60405180910390f35b61006361022a565b604051610052919061034c565b606080606060006001600282805461008790610366565b80601f01602080910402602001604051908101604052809291908181526020018280546100b390610366565b80156101005780601f106100d557610100808354040283529160200191610100565b820191906000526020600020905b8154815290600101906020018083116100e357829003601f168201915b5050505050925081805461011390610366565b80601f016020809104026020016040519081016040528092919081815260200182805461013f90610366565b801561018c5780601f106101615761010080835404028352916020019161018c565b820191906000526020600020905b81548152906001019060200180831161016f57829003601f168201915b5050505050915080805461019f90610366565b80601f01602080910402602001604051908101604052809291908181526020018280546101cb90610366565b80156102185780601f106101ed57610100808354040283529160200191610218565b820191906000526020600020905b8154815290600101906020018083116101fb57829003601f168201915b50505050509050925092509250909192565b60606001805461023990610366565b80601f016020809104026020016040519081016040528092919081815260200182805461026590610366565b80156102b25780601f10610287576101008083540402835291602001916102b2565b820191906000526020600020905b81548152906001019060200180831161029557829003601f168201915b5050505050905090565b6000815180845260005b818110156102e2576020818501810151868301820152016102c6565b818111156102f4576000602083870101525b50601f01601f19169290920160200192915050565b60608152600061031c60608301866102bc565b828103602084015261032e81866102bc565b9050828103604084015261034281856102bc565b9695505050505050565b60208152600061035f60208301846102bc565b9392505050565b600181811c9082168061037a57607f821691505b6020821081141561039b5763b95aa35560e01b600052602260045260246000fd5b5091905056fea26469706673582212203c5ac4a5f7afbe5c7824befbe6e0ca87758fe0c85ffb68270d3f345ea1f9dbef64736f6c634300080b0033a2646970667358221220fd69b0db89142b1601275d60f77e7e3e918126ea2c18a217ad73a61190b3563a64736f6c634300080b0033"
    };

    public static final String SM_BINARY =
            org.fisco.bcos.sdk.v3.utils.StringUtils.joinAll("", SM_BINARY_ARRAY);

    public static final String[] ABI_ARRAY = {
        "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"newEvidenceEvent\",\"type\":\"event\"},{\"conflictFields\":[{\"kind\":0}],\"inputs\":[{\"internalType\":\"string\",\"name\":\"evi\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"info\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"id\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"signAddr\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"message\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"pubKey\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"insertEvidence\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"selector\":[3623411477,2646419633],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]"
    };

    public static final String ABI = org.fisco.bcos.sdk.v3.utils.StringUtils.joinAll("", ABI_ARRAY);

    public static final String FUNC_INSERTEVIDENCE = "insertEvidence";

    public static final Event NEWEVIDENCEEVENT_EVENT =
            new Event(
                    "newEvidenceEvent",
                    Arrays.<TypeReference<?>>asList(new TypeReference<Address>() {}));;

    protected SM2EvidenceVerify(String contractAddress, Client client, CryptoKeyPair credential) {
        super(getBinary(client.getCryptoSuite()), contractAddress, client, credential);
    }

    public static String getBinary(CryptoSuite cryptoSuite) {
        return (cryptoSuite.getCryptoTypeConfig() == CryptoType.ECDSA_TYPE ? BINARY : SM_BINARY);
    }

    public static String getABI() {
        return ABI;
    }

    public List<NewEvidenceEventEventResponse> getNewEvidenceEventEvents(
            TransactionReceipt transactionReceipt) {
        List<Contract.EventValuesWithLog> valueList =
                extractEventParametersWithLog(NEWEVIDENCEEVENT_EVENT, transactionReceipt);
        ArrayList<NewEvidenceEventEventResponse> responses =
                new ArrayList<NewEvidenceEventEventResponse>(valueList.size());
        for (Contract.EventValuesWithLog eventValues : valueList) {
            NewEvidenceEventEventResponse typedResponse = new NewEvidenceEventEventResponse();
            typedResponse.log = eventValues.getLog();
            typedResponse.addr = (String) eventValues.getNonIndexedValues().get(0).getValue();
            responses.add(typedResponse);
        }
        return responses;
    }

    public TransactionReceipt insertEvidence(
            String evi,
            String info,
            String id,
            String signAddr,
            byte[] message,
            byte[] pubKey,
            byte[] r,
            byte[] s) {
        final Function function =
                new Function(
                        FUNC_INSERTEVIDENCE,
                        Arrays.<Type>asList(
                                new org.fisco.bcos.sdk.v3.codec.datatypes.Utf8String(evi),
                                new org.fisco.bcos.sdk.v3.codec.datatypes.Utf8String(info),
                                new org.fisco.bcos.sdk.v3.codec.datatypes.Utf8String(id),
                                new org.fisco.bcos.sdk.v3.codec.datatypes.Address(signAddr),
                                new org.fisco.bcos.sdk.v3.codec.datatypes.generated.Bytes32(
                                        message),
                                new org.fisco.bcos.sdk.v3.codec.datatypes.DynamicBytes(pubKey),
                                new org.fisco.bcos.sdk.v3.codec.datatypes.generated.Bytes32(r),
                                new org.fisco.bcos.sdk.v3.codec.datatypes.generated.Bytes32(s)),
                        Collections.<TypeReference<?>>emptyList(),
                        0);
        return executeTransaction(function);
    }

    public String insertEvidence(
            String evi,
            String info,
            String id,
            String signAddr,
            byte[] message,
            byte[] pubKey,
            byte[] r,
            byte[] s,
            TransactionCallback callback) {
        final Function function =
                new Function(
                        FUNC_INSERTEVIDENCE,
                        Arrays.<Type>asList(
                                new org.fisco.bcos.sdk.v3.codec.datatypes.Utf8String(evi),
                                new org.fisco.bcos.sdk.v3.codec.datatypes.Utf8String(info),
                                new org.fisco.bcos.sdk.v3.codec.datatypes.Utf8String(id),
                                new org.fisco.bcos.sdk.v3.codec.datatypes.Address(signAddr),
                                new org.fisco.bcos.sdk.v3.codec.datatypes.generated.Bytes32(
                                        message),
                                new org.fisco.bcos.sdk.v3.codec.datatypes.DynamicBytes(pubKey),
                                new org.fisco.bcos.sdk.v3.codec.datatypes.generated.Bytes32(r),
                                new org.fisco.bcos.sdk.v3.codec.datatypes.generated.Bytes32(s)),
                        Collections.<TypeReference<?>>emptyList(),
                        0);
        return asyncExecuteTransaction(function, callback);
    }

    public String getSignedTransactionForInsertEvidence(
            String evi,
            String info,
            String id,
            String signAddr,
            byte[] message,
            byte[] pubKey,
            byte[] r,
            byte[] s) {
        final Function function =
                new Function(
                        FUNC_INSERTEVIDENCE,
                        Arrays.<Type>asList(
                                new org.fisco.bcos.sdk.v3.codec.datatypes.Utf8String(evi),
                                new org.fisco.bcos.sdk.v3.codec.datatypes.Utf8String(info),
                                new org.fisco.bcos.sdk.v3.codec.datatypes.Utf8String(id),
                                new org.fisco.bcos.sdk.v3.codec.datatypes.Address(signAddr),
                                new org.fisco.bcos.sdk.v3.codec.datatypes.generated.Bytes32(
                                        message),
                                new org.fisco.bcos.sdk.v3.codec.datatypes.DynamicBytes(pubKey),
                                new org.fisco.bcos.sdk.v3.codec.datatypes.generated.Bytes32(r),
                                new org.fisco.bcos.sdk.v3.codec.datatypes.generated.Bytes32(s)),
                        Collections.<TypeReference<?>>emptyList(),
                        0);
        return createSignedTransaction(function);
    }

    public Tuple8<String, String, String, String, byte[], byte[], byte[], byte[]>
            getInsertEvidenceInput(TransactionReceipt transactionReceipt) {
        String data = transactionReceipt.getInput().substring(10);
        final Function function =
                new Function(
                        FUNC_INSERTEVIDENCE,
                        Arrays.<Type>asList(),
                        Arrays.<TypeReference<?>>asList(
                                new TypeReference<Utf8String>() {},
                                new TypeReference<Utf8String>() {},
                                new TypeReference<Utf8String>() {},
                                new TypeReference<Address>() {},
                                new TypeReference<Bytes32>() {},
                                new TypeReference<DynamicBytes>() {},
                                new TypeReference<Bytes32>() {},
                                new TypeReference<Bytes32>() {}));
        List<Type> results =
                this.functionReturnDecoder.decode(data, function.getOutputParameters());
        return new Tuple8<String, String, String, String, byte[], byte[], byte[], byte[]>(
                (String) results.get(0).getValue(),
                (String) results.get(1).getValue(),
                (String) results.get(2).getValue(),
                (String) results.get(3).getValue(),
                (byte[]) results.get(4).getValue(),
                (byte[]) results.get(5).getValue(),
                (byte[]) results.get(6).getValue(),
                (byte[]) results.get(7).getValue());
    }

    public Tuple2<Boolean, String> getInsertEvidenceOutput(TransactionReceipt transactionReceipt) {
        String data = transactionReceipt.getOutput();
        final Function function =
                new Function(
                        FUNC_INSERTEVIDENCE,
                        Arrays.<Type>asList(),
                        Arrays.<TypeReference<?>>asList(
                                new TypeReference<Bool>() {}, new TypeReference<Address>() {}));
        List<Type> results =
                this.functionReturnDecoder.decode(data, function.getOutputParameters());
        return new Tuple2<Boolean, String>(
                (Boolean) results.get(0).getValue(), (String) results.get(1).getValue());
    }

    public static SM2EvidenceVerify load(
            String contractAddress, Client client, CryptoKeyPair credential) {
        return new SM2EvidenceVerify(contractAddress, client, credential);
    }

    public static SM2EvidenceVerify deploy(Client client, CryptoKeyPair credential)
            throws ContractException {
        return deploy(
                SM2EvidenceVerify.class,
                client,
                credential,
                getBinary(client.getCryptoSuite()),
                getABI(),
                null,
                null);
    }

    public static class NewEvidenceEventEventResponse {
        public TransactionReceipt.Logs log;

        public String addr;
    }
}
